docs(site): make the llms.txt artifacts discoverable, and fix the landing-card parser - #23335
Merged
Merged
Conversation
llms.txt and llms-full.txt are published but nothing points at them: they are static files, so Docusaurus never routes them, the default sitemap omits them, and no page links to them. A crawler or agent can only reach them by guessing the path, which in practice means they are never found — a browsing model asked one flag question read ~20 GitHub issue threads instead, none of which are authoritative. Advertise them three ways: - two <link rel="alternate" type="text/plain"> head tags, so every page declares where the machine-readable copies live - createSitemapItems, appending both URLs to the generated sitemap. The sibling ignorePatterns/lastmod options are closure-bound inside defaultCreateSitemapItems, so appended items are neither filtered nor double-processed and /search stays excluded - a reader-facing section on the MCP page, with a pointer from "Why using Erigon?" The section goes on the MCP page rather than "Why using Erigon?" because the latter is a card-grid landing page, whose body generate-llms.py replaces with synthesized bullets — prose added there would render on the site but never reach llms-full.txt. robots.txt is left alone: there is no standard directive for advertising llms.txt, and the Sitemap: line already there now leads to both files. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dx34ND1m4ySTJXqMR8kRDX
_LANDING_CARD_RE matched a whole card with one pattern: `[^<]+` for the title and description text, `(?:.*?)` for the gaps, under re.DOTALL. `[^<]+` cannot cross a `<`, so a description containing inline markup (<strong>, <code>) fails to match where it stands — and the engine then scans forward through the permissive gap and matches the *next* card's description and </Link>, swallowing the card in between and pairing a title with the wrong description. This is live in the published corpus, on the page whose job is explaining what makes Erigon different. why-using-erigon has 11 cards; llms-full.txt carried 8: Immutable, Decentralised Data <- Staged Sync's description Flexible Pruning <- RPC Providers' description Staged Sync, RPC Providers & Large Stakers, Developers <- absent Parse in two stages instead: match each <Link> block first, then find the title and description within that block only. A card boundary is then unrepresentable, so no match can cross one. Add a count guard. This failed silently for as long as it existed because `--check` only compares generated output against committed output, which makes a systematic generator bug invariant under it: CI stays green while the corpus is wrong. The guard compares parsed cards against lp-card-title occurrences and fails loudly on a mismatch.
Collaborator
Author
|
Companion PR for |
AskAlexSharov
approved these changes
Aug 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
docs.erigon.tech/llms.txtand/llms-full.txtare published, but nothing points anything at them. They are absent fromrobots.txt, absent fromsitemap.xml, and unlinked from every built HTML page. They are static files understatic/, so Docusaurus never routes them and the default sitemap omits them.The effect is measurable. Asked a single Erigon flag question, ChatGPT read 60 sources — roughly 8 doc pages, ~20 GitHub issue threads, 6 unrelated MCP projects, and Wikipedia's article on HTTP — and touched neither file. We are paying to generate a corpus nothing can find.
What this does
Commit 1 — discoverability.
<link rel="alternate" type="text/plain">head tags on every page advertising both.txtURLs.createSitemapItemsappends both URLs to the sitemap, preserving every default entry viadefaultCreateSitemapItems(rest).why-using-erigon.robots.txtis deliberately untouched: no standard directive advertises llms.txt, and theSitemap:line already there now leads to both files.The prose lands on
mcp.mdxrather thanwhy-using-erigon.mdxbecause the latter is a card-grid landing page whose bodysynthesize_landing()replaces wholesale — prose added there would render on the site but never reachllms-full.txt.Commit 2 — a live corpus bug found while writing the above.
_LANDING_CARD_REmatched a whole card with one pattern:[^<]+for the title and description text,(?:.*?)for the gaps, underre.DOTALL.[^<]+cannot cross a<, so a description containing inline markup (<strong>,<code>) fails to match where it stands — and the engine then scans forward through the permissive gap and matches the next card's description and</Link>, swallowing the card in between and pairing a title with the wrong description.This is live today, on the page whose job is explaining what makes Erigon different.
why-using-erigonhas 11 cards;llms-full.txtcarried 8:Fixed by parsing in two stages — match each
<Link>block first, then find title and description within that block only, which makes a card boundary unrepresentable.Plus a count guard. This failed silently for as long as it existed because
--checkonly compares generated output against committed output, which makes a systematic generator bug invariant under it: CI stays green while the corpus is wrong. The guard compares parsed cards againstlp-card-titleoccurrences and fails loudly on a mismatch.A sweep of all 8 card-grid pages confirms
why-using-erigon.mdxis the only file affected.Verification
npm ci && npm run buildclean..txt;/searchstill excluded; 73 per-pagelastmodpreserved.generate-llms.py --checkgreen; 81 tests pass.Note on branches
docs-deploy.ymlcurrently exists only onrelease/3.5, so this publishes once the 3.6 deploy switchover lands.